package com.lry.server;

import com.lry.test.UserServiceImpl;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class RpcServer {

    private String host;
    private int port;
    private List<Object> services;
    private EventLoopGroup boss;
    private EventLoopGroup worker;

    public RpcServer(String host,int port){
        this.host = host;
        this.port = port;
        this.services = new ArrayList<>();
    }

    public RpcServer(int port){
        this("localhost",port);
    }

    public void start(){
        boss = new NioEventLoopGroup(1);
        worker = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        serverBootstrap.group(boss,worker)
        .channel(NioServerSocketChannel.class)
        .option(ChannelOption.SO_BACKLOG,128); //设置线程队列中等待连接的个数
        serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);
        serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE,true);//保持活动连接状态
        serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                ChannelPipeline pipeline = socketChannel.pipeline();
                pipeline.addLast(new ObjectEncoder());
                pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
                pipeline.addLast(new ServerHandler(services));
            }
        });
        try{
            ChannelFuture future = serverBootstrap.bind(host,port).sync();//设置端口  非阻塞
            if(future.isSuccess()){
                System.out.println("server start listen at "+port+" and ready for connections...");
            }
//            future.channel().closeFuture().sync();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            shutDownHook();
        }
    }

    private void shutDownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread(()-> {
            log.info("服务器关闭，开始释放资源，记录设备下线时间");
            try {
                if(boss!=null) {
                    boss.shutdownGracefully().sync();
                }
                if(worker!=null) {
                    worker.shutdownGracefully().sync();
                }
            } catch (InterruptedException e) {
                log.info("bossGroup workerGroup business shutdown 异常");
                e.printStackTrace();
            }
        }));
    }

    public void registerService(Object userService) {
        services.add(userService);
    }
}
